﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Management;

namespace eTerm.NetSocket.Utils
{
    /// <summary>
    /// 系统工具类
    /// </summary>
    public static class SystemUtil {
        [DllImport( "Kernel32.dll" )]
        private static extern Boolean SetSystemTime([In, Out] SystemTime st);


        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        internal struct TokPriv1Luid {
            public int Count;
            public long Luid;
            public int Attr;
        }

        [DllImport("kernel32.dll", ExactSpelling = true)]
        internal static extern IntPtr GetCurrentProcess();

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

        [DllImport("advapi32.dll", SetLastError = true)]
        internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

        [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
        ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        internal static extern bool ExitWindowsEx(int flg, int rea);

        internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int TOKEN_QUERY = 0x00000008;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;
        internal const string SE_SHUTDOWN_NAME = "SeShutdownPrivilege";
        internal const int EWX_LOGOFF = 0x00000000;
        internal const int EWX_SHUTDOWN = 0x00000001;
        internal const int EWX_REBOOT = 0x00000002;
        internal const int EWX_FORCE = 0x00000004;
        internal const int EWX_POWEROFF = 0x00000008;
        internal const int EWX_FORCEIFHUNG = 0x00000010;

        /// <summary>
        /// 关机API
        /// </summary>
        /// <param name="flg"></param>
        public static void DoExitWin(int flg) {
            bool ok;
            TokPriv1Luid tp;
            IntPtr hproc = GetCurrentProcess();
            IntPtr htok = IntPtr.Zero;
            ok = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
            tp.Count = 1;
            tp.Luid = 0;
            tp.Attr = SE_PRIVILEGE_ENABLED;
            ok = LookupPrivilegeValue(null, SE_SHUTDOWN_NAME, ref tp.Luid);
            ok = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
            ok = ExitWindowsEx(flg, 0);
        }



      /// <summary>
      /// 设置系统时间
      /// </summary>
      /// <param name="newdatetime">新时间</param>
      /// <returns></returns>
      public static bool SetSysTime(DateTime newdatetime)
      {
       SystemTime st = new SystemTime();
       st.year    = Convert.ToUInt16(newdatetime.Year);
       st.month   = Convert.ToUInt16(newdatetime.Month);
       st.day    = Convert.ToUInt16(newdatetime.Day);
       st.dayofweek  = Convert.ToUInt16(newdatetime.DayOfWeek);
       st.hour    = Convert.ToUInt16(newdatetime.Hour - TimeZone.CurrentTimeZone.GetUtcOffset(new DateTime(2001,09,01)).Hours);
       st.minute   = Convert.ToUInt16(newdatetime.Minute);
       st.second = Convert.ToUInt16(newdatetime.Second);
       st.milliseconds = Convert.ToUInt16(newdatetime.Millisecond);
       return SetSystemTime(st);
      }

      /// <summary>
      /// Gets the serial number.
      /// </summary>
      /// <returns></returns>
      public static string GetSerialNumber() {
          StringBuilder sb = new StringBuilder();
          byte[] KeyNumbers = TEACrypter.MD5(Encoding.Default.GetBytes(Encrypt(GetCpuSN())));
          foreach (byte SnByte in KeyNumbers)
          {
              sb.Append(String.Format("{0:X}", SnByte).PadLeft(2, '0'));
          }
          return sb.ToString();
      }

      /// <summary>
      /// Encrypts the specified STR input.
      /// </summary>
      /// <param name="strInput">The STR input.</param>
      /// <returns></returns>
      static string Encrypt(string strInput)
      {
          string strFont, strEnd;
          string strOutput;
          char[] charFont;
          int i, len, intFont;

          len = strInput.Length;
          //Console.WriteLine(" strInput 's length is :{0} \n", len);
          strFont = strInput.Remove(len - 1, 1);
          strEnd = strInput.Remove(0, len - 1);

          //Console.WriteLine(" strFont is : {0} \n" , strFont);                                 
          //Console.WriteLine(" strEnd is : {0} \n" , strEnd);                                 

          charFont = strFont.ToCharArray();
          for (i = 0; i < strFont.Length; i++)
          {
              intFont = (int)charFont[i] + 3;
              //Console.WriteLine(" intFont is : {0} \n", intFont);                                 

              charFont[i] = Convert.ToChar(intFont);
              //Console.WriteLine("charFont[{0}] is : {1}\n", i, charFont[i]);                                 
          }
          strFont = ""; //let strFont  null
          for (i = 0; i < charFont.Length; i++)
          {
              strFont += charFont[i];
          }
          strOutput = strEnd + strFont;
          return strOutput;

      }



      /// <summary>
      /// Gets the cpu SN.
      /// </summary>
      /// <returns></returns>
      public static string GetCpuSN()
      {
          ManagementClass cimobject = new ManagementClass("Win32_Processor");
          ManagementObjectCollection moc = cimobject.GetInstances();
          StringBuilder sb = new StringBuilder();
          foreach (ManagementObject mo in moc)
          {
              sb.Append(mo.Properties["ProcessorId"].Value.ToString().Replace(":", string.Empty).Replace(" ", string.Empty));
          }


          using (ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration"))
          {
              ManagementObjectCollection moc2 = mc.GetInstances();
              foreach (ManagementObject mo in moc2)
              {
                  if ((bool)mo["IPEnabled"] == true)
                      sb.Append(mo["MacAddress"].ToString().Replace(@":", string.Empty));
                  mo.Dispose();
              }
          }
          return sb.ToString();
      }
    }





    /// <summary>
    ///系统时间类
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    internal class SystemTime {
        public ushort year;
        public ushort month;
        public ushort dayofweek;
        public ushort day;
        public ushort hour;
        public ushort minute;
        public ushort second;
        public ushort milliseconds;
    }

}
